#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
MyBatis日志生成器
支持生成多种格式的MyBatis日志文件，用于测试日志分析系统
"""

import random
import datetime
import argparse
import os
import sys

class MyBatisLogGenerator:
    def __init__(self):
        # 线程池配置
        self.threads = [f'http-nio-8080-exec-{i}' for i in range(1, 21)]
        
        # Mapper类配置
        self.mappers = [
            'com.example.mapper.UserMapper',
            'com.example.mapper.OrderMapper', 
            'com.example.mapper.ProductMapper',
            'com.example.mapper.CategoryMapper',
            'com.example.mapper.PaymentMapper',
            'com.example.mapper.InventoryMapper',
            'com.example.mapper.CustomerMapper',
            'com.example.mapper.SupplierMapper'
        ]
        
        # SQL语句模板
        self.sql_templates = {
            'SELECT': [
                'SELECT * FROM users WHERE id = ?',
                'SELECT * FROM users WHERE username = ? AND status = ?',
                'SELECT u.*, o.* FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE u.id = ?',
                'SELECT COUNT(*) FROM orders WHERE user_id = ? AND create_time > ?',
                'SELECT p.*, c.name as category_name FROM products p LEFT JOIN categories c ON p.category_id = c.id WHERE p.price > ?',
                'SELECT * FROM products WHERE category_id = ? ORDER BY price DESC LIMIT ? OFFSET ?',
                'SELECT DISTINCT user_id FROM orders WHERE status = ? AND create_time BETWEEN ? AND ?',
                'SELECT p.name, AVG(r.rating) as avg_rating FROM products p LEFT JOIN reviews r ON p.id = r.product_id GROUP BY p.id HAVING avg_rating > ?'
            ],
            'INSERT': [
                'INSERT INTO users (username, email, password, create_time) VALUES (?, ?, ?, ?)',
                'INSERT INTO orders (user_id, product_id, quantity, price, status) VALUES (?, ?, ?, ?, ?)',
                'INSERT INTO products (name, description, price, category_id, stock) VALUES (?, ?, ?, ?, ?)',
                'INSERT INTO payments (order_id, amount, payment_method, status) VALUES (?, ?, ?, ?)',
                'INSERT INTO inventory (product_id, quantity, warehouse_id, update_time) VALUES (?, ?, ?, ?)'
            ],
            'UPDATE': [
                'UPDATE users SET last_login_time = ? WHERE id = ?',
                'UPDATE orders SET status = ?, update_time = ? WHERE id = ?',
                'UPDATE products SET stock = stock - ? WHERE id = ? AND stock >= ?',
                'UPDATE customers SET email = ?, phone = ? WHERE id = ?',
                'UPDATE inventory SET quantity = ?, update_time = ? WHERE product_id = ? AND warehouse_id = ?'
            ],
            'DELETE': [
                'DELETE FROM users WHERE id = ?',
                'DELETE FROM orders WHERE id = ? AND user_id = ?',
                'DELETE FROM products WHERE id = ? AND category_id = ?',
                'DELETE FROM inventory WHERE product_id = ? AND warehouse_id = ?',
                'DELETE FROM payments WHERE order_id = ? AND status = ?'
            ]
        }
        
        # 参数模板
        self.param_templates = {
            'Integer': ['123', '456', '789', '1001', '2002', '3003', '5000', '10000'],
            'String': ['"admin"', '"user123"', '"test@example.com"', '"active"', '"pending"', '"completed"'],
            'Date': ['2024-01-01', '2024-06-15', '2024-12-31', '2023-01-01', '2023-12-31'],
            'Boolean': ['true', 'false'],
            'Double': ['99.99', '199.99', '299.99', '599.99', '999.99', '1999.99']
        }
        
        # 日志级别
        self.log_levels = ['DEBUG', 'TRACE']
        
    def generate_params(self, sql):
        """根据SQL生成参数"""
        params = []
        param_count = sql.count('?')
        
        for i in range(param_count):
            # 根据SQL内容智能选择参数类型
            if 'id' in sql.lower() and i == 0:
                param_type = 'Integer'
            elif 'price' in sql.lower():
                param_type = 'Double'
            elif 'time' in sql.lower() or 'date' in sql.lower():
                param_type = 'Date'
            elif 'status' in sql.lower():
                param_type = 'String'
            else:
                param_type = random.choice(list(self.param_templates.keys()))
            
            param_value = random.choice(self.param_templates[param_type])
            params.append(f"{param_value}({param_type})")
        
        return params
    
    def generate_sql_execution(self, start_time, is_slow=False):
        """生成一个完整的SQL执行记录"""
        thread = random.choice(self.threads)
        mapper = random.choice(self.mappers)
        sql_type = random.choice(list(self.sql_templates.keys()))
        sql = random.choice(self.sql_templates[sql_type])
        params = self.generate_params(sql)
        
        # 生成时间戳
        preparing_time = start_time
        parameters_time = start_time + datetime.timedelta(milliseconds=random.randint(1, 50))
        
        if is_slow:
            # 慢SQL：执行时间超过5秒
            total_time = start_time + datetime.timedelta(seconds=random.randint(5, 30))
        else:
            # 正常SQL：执行时间1-100毫秒
            total_time = start_time + datetime.timedelta(milliseconds=random.randint(1, 100))
        
        # 生成日志行
        lines = []
        
        # Preparing行
        preparing_line = f"{preparing_time.strftime('%Y-%m-%d %H:%M:%S')} [{thread}] DEBUG {mapper} - ==>  Preparing: {sql}"
        lines.append(preparing_line)
        
        # Parameters行
        params_str = ", ".join(params)
        parameters_line = f"{parameters_time.strftime('%Y-%m-%d %H:%M:%S')} [{thread}] DEBUG {mapper} - ==> Parameters: {params_str}"
        lines.append(parameters_line)
        
        # Total行
        total_count = random.randint(0, 1000)
        total_line = f"{total_time.strftime('%Y-%m-%d %H:%M:%S')} [{thread}] TRACE {mapper} - <==      Total: {total_count}"
        lines.append(total_line)
        
        return lines, total_time
    
    def generate_log_file(self, filename, target_size_mb, slow_sql_ratio=0.1):
        """生成指定大小的日志文件"""
        print(f"开始生成MyBatis日志文件: {filename}")
        print(f"目标大小: {target_size_mb}MB")
        print(f"慢SQL比例: {slow_sql_ratio * 100}%")
        
        target_size = target_size_mb * 1024 * 1024  # 转换为字节
        current_size = 0
        sql_count = 0
        slow_sql_count = 0
        
        # 起始时间
        start_time = datetime.datetime.now() - datetime.timedelta(hours=1)
        
        with open(filename, 'w', encoding='utf-8') as f:
            while current_size < target_size:
                # 决定是否为慢SQL
                is_slow = random.random() < slow_sql_ratio
                
                # 生成SQL执行记录
                lines, next_start_time = self.generate_sql_execution(start_time, is_slow)
                
                # 写入文件
                for line in lines:
                    f.write(line + '\n')
                    current_size += len(line) + 1  # +1 for newline
                
                sql_count += 1
                if is_slow:
                    slow_sql_count += 1
                
                # 更新时间
                start_time = next_start_time + datetime.timedelta(seconds=random.randint(1, 10))
                
                # 每1000条SQL显示进度
                if sql_count % 1000 == 0:
                    progress = (current_size / target_size) * 100
                    print(f"已生成 {sql_count} 条SQL，当前大小: {current_size // 1024 // 1024}MB ({progress:.1f}%)")
        
        print(f"\n生成完成: {filename}")
        print(f"文件大小: {current_size // 1024 // 1024}MB")
        print(f"总SQL数量: {sql_count}")
        print(f"慢SQL数量: {slow_sql_count} (执行时间>5秒)")
        print(f"慢SQL比例: {(slow_sql_count / sql_count) * 100:.1f}%")
        
        return filename, sql_count, slow_sql_count

def main():
    parser = argparse.ArgumentParser(description='MyBatis日志生成器')
    parser.add_argument('-s', '--size', type=int, default=10, help='目标文件大小(MB)，默认10MB')
    parser.add_argument('-f', '--filename', type=str, default='mybatis_test.log', help='输出文件名')
    parser.add_argument('-r', '--ratio', type=float, default=0.1, help='慢SQL比例(0-1)，默认0.1')
    parser.add_argument('--slow-only', action='store_true', help='只生成慢SQL')
    parser.add_argument('--normal-only', action='store_true', help='只生成正常SQL')
    
    args = parser.parse_args()
    
    # 参数验证
    if args.size <= 0:
        print("错误: 文件大小必须大于0")
        sys.exit(1)
    
    if args.ratio < 0 or args.ratio > 1:
        print("错误: 慢SQL比例必须在0-1之间")
        sys.exit(1)
    
    if args.slow_only and args.normal_only:
        print("错误: 不能同时指定--slow-only和--normal-only")
        sys.exit(1)
    
    # 调整慢SQL比例
    if args.slow_only:
        args.ratio = 1.0
    elif args.normal_only:
        args.ratio = 0.0
    
    # 生成日志文件
    generator = MyBatisLogGenerator()
    filename, sql_count, slow_sql_count = generator.generate_log_file(
        args.filename, 
        args.size, 
        args.ratio
    )
    
    print(f"\n✅ 日志文件生成成功: {filename}")
    print(f"📊 统计信息:")
    print(f"   - 文件大小: {os.path.getsize(filename) // 1024 // 1024}MB")
    print(f"   - 总SQL数量: {sql_count}")
    print(f"   - 慢SQL数量: {slow_sql_count}")
    print(f"   - 慢SQL比例: {(slow_sql_count / sql_count) * 100:.1f}%")
    
    print(f"\n🚀 使用说明:")
    print(f"   1. 将生成的 {filename} 上传到日志分析系统")
    print(f"   2. 选择对应的MyBatis日志模板")
    print(f"   3. 开始分析，系统将自动检测慢SQL")

if __name__ == "__main__":
    main() 